﻿using NoteManger;
using System;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using WebCache;
using WorkWriter.Models;

namespace WorkWriter.Controllers
{
    public class AccountController : BaseController
    {
        private const string REMEMBER_PERFIX = "~RememberMe:";
        private const string REMEMBER_ID_PERFIX = "LOGIN:";
        private const string MAIL_CONTENT = @"ミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミ
ミ
ミ
ミ      WorkWirter密码找回
ミ
ミ      您的密码已重置成功，新密码为：{0} (自动邮件，请勿回复)。
ミ
ミ      登录后，请及时修改。
ミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミミ";
        //
        // GET: /Account/Index

        public ActionResult Index()
        {
            return View();
        }

        //
        // GET: /Account/Login
        [AllowAnonymous]
        public ActionResult Login()
        {
            return View();
        }

        //
        // POST: /Account/Login
        [AllowAnonymous]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Login(LoginModel model, string returnUrl)
        {
            CacheProviders.SessionCache.Clear();
            ViewData["RememberMe"] = model.RememberMe ? 1 : 0;
            if (ModelState.IsValid)
            {
                //if (Membership.ValidateUser(model.UserName, model.Password))
                object[] loginResult = new object[0];
                string loginMessage = string.Empty;
                string password = model.Password ?? string.Empty;
                if (password.StartsWith(REMEMBER_PERFIX)) password = NoteRemote.Decrypt(password.Substring(REMEMBER_PERFIX.Length).Replace(" ", "+"));//jquery cookie 无法读取+号的bug.
                if (noteContext.UserLogin(model.UserName, password, ref loginResult, ref loginMessage))
                {
                    //this._NoteRemoteObject.UserLogin(this.tboxUserID.Text.Trim(), this.tboxUserPwd.Text.Trim(), ref array, ref text);
                    //this._LoginInfo.LoginSuccess = (bool)array[0];
                    //this._LoginInfo.LoginID = (string)array[1];
                    //this._LoginInfo.LoginName = (string)array[2];
                    //this._LoginInfo.DepID = (string)array[3];
                    //this._LoginInfo.GroupID = (string)array[4];
                    //this._LoginInfo.PurviewID = (string)array[5];
                    SysContext.User = new TLoginInfo { LoginID = model.UserName, LoginName = Convert.ToString(loginResult[2]) };
                    HttpCookie rememberCookie = Request.Cookies[REMEMBER_ID_PERFIX + SysContext.User.LoginID];
                    if (model.RememberMe)
                    {
                        if (rememberCookie == null)
                        {
                            rememberCookie = new HttpCookie(REMEMBER_ID_PERFIX + SysContext.User.LoginID, REMEMBER_PERFIX + NoteRemote.Encrypt(password));
                            Response.Cookies.Add(rememberCookie);
                        }
                        else
                        {
                            rememberCookie.Value = REMEMBER_PERFIX + NoteRemote.Encrypt(password);
                        }
                    }
                    else
                    {
                        if (rememberCookie != null)
                        {
                            rememberCookie.Expires = DateTime.Now.AddDays(-1);
                            Response.Cookies.Add(rememberCookie);
                        }
                    }

                    if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "提供的用户名或密码不正确。");
                }
            }

            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        //
        // GET: /Account/LogOff

        public ActionResult LogOff()
        {
            CacheProviders.SessionCache.Clear();
            SysContext.User = null;
            return RedirectToAction("Login");
        }
        //
        // GET: /Account/ChangePassword

        public ActionResult ChangePassword()
        {
            return View();
        }

        //
        // POST: /Account/ChangePassword

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    if (model.OldPassword == null) model.OldPassword = string.Empty;
                    if (model.NewPassword == null) model.NewPassword = string.Empty;
                    if (!Regex.IsMatch(model.OldPassword, "^[0-9a-zA-Z]*$")) throw new LogicException("原密码不正确。");
                    else if (!Regex.IsMatch(model.NewPassword, "^[0-9a-zA-Z]*$")) throw new LogicException("密码只能由字母和数字组成。");

                    string[,] arrInfo = new string[0, 0];
                    string message = string.Empty;
                    var success = noteContext.CommonQuery(string.Format("select EmpID,EmpPwd from Employees (NOLOCK) where EmpID = '{0}'", SysContext.User.LoginID), ref arrInfo, ref message);
                    if (arrInfo.Length == 0) throw new LogicException("工号不存在。");

                    var oldEnPwd = NoteRemote.Encrypt(SysContext.User.LoginID + model.OldPassword);
                    var newEnPwd = NoteRemote.Encrypt(SysContext.User.LoginID + model.NewPassword);
                    if (oldEnPwd != arrInfo[0, 1]) throw new LogicException("原密码输入不正确。");

                    arrInfo = new string[0, 0];
                    noteContext.CommonQuery(string.Format("update Employees set EmpPwd='{0}' where EmpID='{1}' SELECT 'T'", newEnPwd, SysContext.User.LoginID), ref arrInfo, ref message);
                    if (arrInfo.Length == 0 || arrInfo[0, 0] != "T") throw new LogicException("密码找回失败，请重试。");

                    return RedirectToAction("ChangePasswordSuccess");
                }
                catch (LogicException ex)
                {
                    ModelState.AddModelError("change_pwd", ex.Message);
                }
            }
            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        //
        // GET: /Account/ChangePasswordSuccess

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Forget()
        {
            ViewBag.SubmitSuccess = false;
            return View();
        }

        [HttpPost]
        public ActionResult Forget(string userid)
        {
            var info = new { UserName = Request["UserName"], TelNo = Request["TelNo"], Email = Request["Email"] };
            string empName = string.Empty;
            try
            {
                if (!Regex.IsMatch(info.UserName, "^[0-9a-zA-Z]+$")) throw new LogicException("工号不正确。");
                string[,] arrInfo = new string[0, 0];
                string message = string.Empty;
                var success = noteContext.CommonQuery(string.Format("select Phone,EMail,EmpName,ExPhone from Employees (NOLOCK) where EmpID = '{0}'", info.UserName), ref arrInfo, ref message);
                if (arrInfo.Length == 0) throw new LogicException("工号不存在。");
                else if ((string.IsNullOrWhiteSpace(arrInfo[0, 0]) && info.TelNo != "X") || info.TelNo != arrInfo[0, 0]) throw new LogicException("手机号不正确。");
                else if (info.Email != arrInfo[0, 1]) throw new LogicException("注册邮箱不正确。");

                empName = arrInfo[0, 2];
                var randPwd = this.GetRandomPwd(6);
                var newPwd = NoteRemote.Encrypt(info.UserName + randPwd);

                arrInfo = new string[0, 0];
                noteContext.CommonQuery(string.Format("update Employees set EmpPwd='{0}' where EmpID='{1}' SELECT 'T'", newPwd, info.UserName), ref arrInfo, ref message);
                if (arrInfo.Length == 0 || arrInfo[0, 0] != "T") throw new LogicException("密码找回失败，请重试。");
                this.SendEmail(info.Email, empName, "WorkWirter密码找回", string.Format(MAIL_CONTENT, randPwd));
                ViewBag.SubmitSuccess = true;
                ModelState.Remove("forget");
            }
            catch (LogicException ex)
            {
                ViewBag.SubmitSuccess = false;
                ModelState.AddModelError("forget", ex.Message);
            }

            return View(info);
        }

        private void SendEmail(string email, string name, string title, string msg)
        {
            string passwd = NoteRemote.Decrypt(System.IO.File.ReadAllText("c:\\163mail.txt"));
            //确定smtp服务器地址。实例化一个Smtp客户端
            SmtpClient client = new SmtpClient("smtp.163.com");
            //发送地址
            string sender = "workwriter@163.com";
            //构造一个发件人地址对象
            MailAddress from = new MailAddress(sender, "WorkWriter", Encoding.UTF8);
            //构造一个收件人地址对象
            MailAddress to = new MailAddress(email, name, Encoding.UTF8);

            //构造一个Email的Message对象
            MailMessage message = new MailMessage(from, to);

            # region Attachments
            //为 message 添加附件
            //foreach (TreeNode treeNode in treeViewFileList.Nodes)
            //{
            //    //得到文件名
            //    string fileName = treeNode.Text;
            //    //判断文件是否存在
            //    if (File.Exists(fileName))
            //    {
            //        //构造一个附件对象
            //        Attachment attach = new Attachment(fileName);
            //        //得到文件的信息
            //        ContentDisposition disposition = attach.ContentDisposition;
            //        disposition.CreationDate = System.IO.File.GetCreationTime(fileName);
            //        disposition.ModificationDate = System.IO.File.GetLastWriteTime(fileName);
            //        disposition.ReadDate = System.IO.File.GetLastAccessTime(fileName);
            //        //向邮件添加附件
            //        message.Attachments.Add(attach);
            //    }
            //    else
            //    {
            //        MessageBox.Show("文件" + fileName + "未找到！");
            //    }
            //}
            #endregion

            //添加邮件主题和内容
            message.Subject = title;
            message.SubjectEncoding = Encoding.UTF8;
            message.Body = msg;
            message.BodyEncoding = Encoding.UTF8;

            //设置邮件的信息
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            message.BodyEncoding = System.Text.Encoding.UTF8;
            message.IsBodyHtml = false;

            //如果服务器支持安全连接，则将安全连接设为true。
            //gmail支持，163不支持，如果是gmail则一定要将其设为true
            client.EnableSsl = false;

            #region ssl
            //if (cmbBoxSMTP.SelectedText == "smpt.163.com")
            //    client.EnableSsl = false;
            //else
            //    client.EnableSsl = true;
            #endregion

            //设置用户名和密码。
            //string userState = message.Subject;
            client.UseDefaultCredentials = false;
            string username = "workwriter";
            //用户登陆信息
            NetworkCredential myCredentials = new NetworkCredential(username, passwd);
            client.Credentials = myCredentials;
            //发送邮件
            client.Send(message);
        }

        private string GetRandomPwd(int length)
        {
            char[] chars = new char[62];
            int index = 0;
            for (int i = 48; i < 58; i++) chars[index++] = (char)i;
            for (int i = 65; i < 91; i++) chars[index++] = (char)i;
            for (int i = 97; i < 123; i++) chars[index++] = (char)i;

            char[] newChars = new char[length];
            var rand = new Random();
            for (int i = 0; i < newChars.Length; i++) newChars[i] = chars[rand.Next(chars.Length)];
            return new string(newChars);
        }

        #region 状态代码
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // 请参见 http://go.microsoft.com/fwlink/?LinkID=177550 以查看
            // 状态代码的完整列表。
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "用户名已存在。请输入其他用户名。";

                case MembershipCreateStatus.DuplicateEmail:
                    return "该电子邮件地址的用户名已存在。请输入其他电子邮件地址。";

                case MembershipCreateStatus.InvalidPassword:
                    return "提供的密码无效。请输入有效的密码值。";

                case MembershipCreateStatus.InvalidEmail:
                    return "提供的电子邮件地址无效。请检查该值并重试。";

                case MembershipCreateStatus.InvalidAnswer:
                    return "提供的密码取回答案无效。请检查该值并重试。";

                case MembershipCreateStatus.InvalidQuestion:
                    return "提供的密码取回问题无效。请检查该值并重试。";

                case MembershipCreateStatus.InvalidUserName:
                    return "提供的用户名无效。请检查该值并重试。";

                case MembershipCreateStatus.ProviderError:
                    return "身份验证提供程序返回了错误。请验证您的输入并重试。如果问题仍然存在，请与系统管理员联系。";

                case MembershipCreateStatus.UserRejected:
                    return "已取消用户创建请求。请验证您的输入并重试。如果问题仍然存在，请与系统管理员联系。";

                default:
                    return "发生未知错误。请验证您的输入并重试。如果问题仍然存在，请与系统管理员联系。";
            }
        }
        #endregion
    }
}
